/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package program.bl;

import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import program.beans.Page;

/**
 * Controller-class for pages, implemented in singleton singleton
 *
 * Responsible: Bernhard
 */
public class PDFViewerController {

    private static PDFViewerController instance;
    private List<Page> pages = new ArrayList<>();

    private PDFViewerController() {
    }

    public static PDFViewerController getInstance() {
        if (instance == null) {
            instance = new PDFViewerController();
        }

        return instance;
    }

    /**
     * Read pages from delivered file and write them into pages-list
     * 
     * @param file
     */
    public void setPages(File file) throws Exception {
        System.out.println(file.getPath() + "200");
        pages.clear();
        if (file.isDirectory()) {
            File[] folderContent = file.listFiles();
            for (int i = 0; i < folderContent.length; i++) {
                File f = folderContent[i];
                String fileName = f.getName();
                if (f.isFile() && (fileName.endsWith(".jpg")
                        || fileName.endsWith(".png"))) {

                    Image img = null;
                    try {
                        img = ImageIO.read(f);
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(null, ex);

                    }

                    pages.add(new Page(i + 1, img));

                }
            }
        } else if (file.isFile() && file.getName().endsWith(".pdf")) {

            RandomAccessFile raf = new RandomAccessFile(file, "r");
            FileChannel fc = raf.getChannel();
            ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            PDFFile pdfFile = new PDFFile(buf);
            this.setPages(pdfFile);
        }
    }

    /**
     * Read pages from delivered pdf-file and write them into pages-list
     * 
     * @param file 
     */
    public void setPages(PDFFile file) {
        pages.clear();
        for (int i = 0; i < file.getNumPages(); i++) {
            PDFPage page = file.getPage(i + 1);

            Rectangle2D r2d = page.getBBox();

            double width = r2d.getWidth();
            double height = r2d.getHeight();

            width /= 72.0;
            height /= 72.0;

            int res = Toolkit.getDefaultToolkit().getScreenResolution();
            width *= res;
            height *= res;

            Image image = page.getImage((int) width, (int) height, r2d, null, true, true);

            pages.add(new Page(i + 1, image));
        }
    }

    public List<Page> getAllPages(int width, int height) {
        List<Page> newPages = new ArrayList<>();
        for (int i = 0; i < pages.size(); i++) {
            Page p = pages.get(i);
            Image img = null;
            if (width == -1 || height == -1) {
                img = p.getImage();
            } else {
                img = p.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
            }
            Page newPage = new Page(p.getPageNumber(), img);
            newPages.add(newPage);
        }

        return newPages;
    }

    /**
     * Edits page with delivered pageNumber and updates it in the page-list
     * 
     * @param pageNumber number of the page which should be updated
     * @param newPage new page
     */
    public void updatePage(int pageNumber, Image newPage) {
        Page p = new Page(pageNumber, newPage);
        pages.remove(pageNumber - 1);
        pages.add(pageNumber - 1, p);
    }

    /**
     * Deletes page with delivered pageNumber from page-list
     * 
     * @param pageNumber number of the page which should be deleted
     */
    public void deletePage(int pageNumber) {
        pages.remove(pageNumber - 1);
        for (int i = 0; i < pages.size(); i++) {
            Page p = pages.get(i);
            p.setPageNumber(i + 1);
        }
    }

    /**
     * Returns the image of each page of the page-list
     * 
     * @return image of each page of the page-list
     */
    public ArrayList<Image> getAllImages() {
        ArrayList<Image> images = new ArrayList<>();
        for (int i = 0; i < pages.size(); i++) {
            Image img = pages.get(i).getImage();
            images.add(i, img);
        }

        return images;
    }

    public int getNumberOfPages() {
        return pages.size();
    }

    public void addPage(Image img) {
        Page p = new Page(pages.size() + 1, img);
        pages.add(p);
    }

    /**
     * Returns page with delivered pageNumber
     * 
     * @param pageNumber of page, which should be returned
     * @return page with delivered pageNumber
     */
    public Image getPage(int pageNumber) {
        return pages.get(pageNumber).getImage();
    }

    public List<Page> getPages() {
        return pages;
    }

    public void setPages(List<Page> pages) {
        this.pages = pages;
    }
}
